package com.yonyou.crm.sys.modules.service;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;

import com.yonyou.crm.common.biz.service.BaseBizServiceImpl;
import com.yonyou.crm.common.exception.CrmBusinessException;
import com.yonyou.crm.common.login.context.LoginContextConstant;
import com.yonyou.crm.sys.modules.entity.BiztypeRoleVO;
import com.yonyou.crm.sys.modules.entity.BiztypeVO;
import com.yonyou.crm.sys.modules.entity.ModuleVO;
import com.yonyou.crm.sys.modules.events.BiztypeDeleteEvent;
import com.yonyou.iuap.context.InvocationInfoProxy;
import com.yonyou.crm.sys.role.entity.RoleVO;
import com.yonyou.crm.sys.role.service.RoleBizServiceImpl;

@Service
public class BiztypeBizServiceImpl extends BaseBizServiceImpl<BiztypeVO>{

	@Autowired
	private RoleBizServiceImpl roleBizServiceImpl;
	
	@Autowired
	private AdministratorManage administratorManage;
	
	@Autowired
	private ModuleBizServiceImpl moduleBizServiceImpl;
	
	@Autowired
	private  ApplicationEventPublisher publisher;
	
	@Autowired
	private LayoutBizServiceImpl layoutBizServiceImpl;
	
	@Autowired
	private CustomIdGeneratorBizServiceImpl customIdGeneratorBizServiceImpl;
	
	public List<BiztypeVO> getBiztypeList(Long objId) {
		String tenantIdStr = (String) InvocationInfoProxy.getTenantid();
		Long tenantId = Long.parseLong(tenantIdStr);
		Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("tenantId", tenantId);
		paramMap.put("objId", objId);
		List<BiztypeVO> bizTypeList = new ArrayList<BiztypeVO>();
		bizTypeList = dao	.selectVoList(BiztypeVO.class, "ListBiztype", paramMap);
		List<Long> customBiztypes = new ArrayList<Long>();
		for (BiztypeVO biztypeVO : bizTypeList) {
			if (biztypeVO.getTenantId() != 0) {
				customBiztypes.add(biztypeVO.getId());
			}
		}
        
		Iterator<BiztypeVO> it = bizTypeList.iterator();
		// TODO 先简单循环来取，到时候会换成批量处理
		while (it.hasNext()) {
			BiztypeVO biztype = it.next();
			if (biztype.getTenantId() == 0
					&& customBiztypes.contains(biztype.getId())) {
				it.remove();
				continue;
			}
			if (biztype.getIsDeleted() ==1) {
				it.remove();				
			} else {
				List<RoleVO> roleList = getRoleListByBiztypeId(biztype.getId());
				biztype.setRoles(roleList);
			}
		}
		return bizTypeList;
	}

	public BiztypeVO getBiztype(Long id) {
		String tenantIdStr = (String) InvocationInfoProxy.getTenantid();
		Long tenantId = Long.parseLong(tenantIdStr);
		Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("tenantId", tenantId);
		paramMap.put("id", id);
		List<BiztypeVO> bizTypeList = new ArrayList<BiztypeVO>();
		bizTypeList = dao	.selectVoList(BiztypeVO.class, "ListBiztype", paramMap);
		BiztypeVO aBiztypeVO = new BiztypeVO();
		for (BiztypeVO biztypeVO : bizTypeList) {
			aBiztypeVO = biztypeVO;
			if (biztypeVO.getTenantId() != 0) {
					break;
			}
		}
		List<RoleVO> roleList = getRoleListByBiztypeId(id);
		aBiztypeVO.setRoles(roleList);
		return aBiztypeVO;
        
	}
	
	public BiztypeVO saveBiztype(BiztypeVO biztypeVO) {

		String tenantIdStr = (String) InvocationInfoProxy.getTenantid();
		Long tenantId = Long.parseLong(tenantIdStr);
		String userIdStr = (String)InvocationInfoProxy.getParameter("id");//用户id
		Long userId = Long.parseLong(userIdStr);
		if (!administratorManage.isAdmin(userId)) {
			throw new CrmBusinessException("没有该功能的操作权限");
		}
		biztypeVO.setTenantId(tenantId);
		biztypeVO.setIsCustom(1);
		Date date = new Date();
		biztypeVO.setSysCreatedTime(date);
		biztypeVO.setCreatedTime(date);
		biztypeVO.setModifiedTime(date);
		biztypeVO.setSysModifiedTime(date);
		biztypeVO.setSysCreatedUserId(userId);
		biztypeVO.setSysModifiedUserId(userId);
		biztypeVO.setSortOrder(date.getTime());
		Long id = getNextId();
		biztypeVO.setId(id);
		super.saveVO(biztypeVO);
		List<Long> roleIds  = biztypeVO.getRoleIds();
		addRoles(id, roleIds);
		List<RoleVO> roleList = new ArrayList<RoleVO>();
		if (roleIds != null) {
			for (int i=0;i<roleIds.size();i++) {
				Long roleId = roleIds.get(i);
				RoleVO role  = roleBizServiceImpl.getROleDetail(roleId);
				roleList.add(role);
			}
		}
		biztypeVO.setRoles(roleList);
		return biztypeVO;
	}

	public BiztypeVO updateBiztype(BiztypeVO biztypeVO) {
		String tenantIdStr = (String) InvocationInfoProxy.getTenantid();
		Long tenantId = Long.parseLong(tenantIdStr);
		String userIdStr = (String)InvocationInfoProxy.getParameter("id");//用户id
		Long userId = Long.parseLong(userIdStr);
		if (!administratorManage.isAdmin(userId)) {
			throw new CrmBusinessException("没有该功能的操作权限");
		}
		updateBiztypeOnly(biztypeVO);
		// 默认布局不能分配角色，默认所有角色可用。 
		if (biztypeVO.getIsDefault() == 0) {
			// 批量删除原有角色
			Map<String, Object> roleDelCond = new HashMap<String, Object>();
			roleDelCond.put("tenantId", tenantId);
			roleDelCond.put("biztypeId", biztypeVO.getId());
			dao.delete(BiztypeRoleVO.class,"DeleteByBiztypeId",roleDelCond);
			// 批量添加新角色
			List<Long> roleIds  = biztypeVO.getRoleIds();
			addRoles(biztypeVO.getId(), roleIds);
			List<RoleVO> roleList = new ArrayList<RoleVO>();
			if (roleIds != null) {
				for (int i=0;i<roleIds.size();i++) {
					Long roleId = roleIds.get(i);
					RoleVO role  = roleBizServiceImpl.getROleDetail(roleId);
					roleList.add(role);
				}
			}
			biztypeVO.setRoles(roleList);
		} 
		return biztypeVO;
	}

	public List<RoleVO> getRoleListByBiztypeId(Long biztypeId) {
		String tenantIdStr = (String) InvocationInfoProxy.getTenantid();
		Long tenantId = Long.parseLong(tenantIdStr);
		Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("tenantId", tenantId);
		paramMap.put("biztypeId", biztypeId);
		List<RoleVO> roleList = new ArrayList<RoleVO>();
		List<BiztypeRoleVO> biztypeRoles = dao.selectVoList(BiztypeRoleVO.class, "ListBiztypeRole", paramMap);
		List<Long> customBiztypeRoles = new ArrayList<Long>();
		List<Long> defaultBiztypeRoles = new ArrayList<Long>();
		for (BiztypeRoleVO bizrole : biztypeRoles) {
			if (bizrole.getTenantId() != 0) {
				customBiztypeRoles.add(bizrole.getRoleId());
			} else {
				defaultBiztypeRoles.add(bizrole.getRoleId());				
			}
		}

        if (customBiztypeRoles.size() != 0) {
        	 // 通过customBiztypeRoles获取角色列表
    		// TODO 批量获取获取角色列表
    		for (Integer i=0;i<customBiztypeRoles.size();i++) {
    			Long roleId = customBiztypeRoles.get(i);
    			RoleVO role  = roleBizServiceImpl.getROleDetail(roleId);
    			roleList.add(role);
    		}
        } else {
        	// 通过defaultBiztypeRoles获取角色列表
    		for (Integer i=0;i<defaultBiztypeRoles.size();i++) {
    			Long roleId = defaultBiztypeRoles.get(i);
    			RoleVO role  = roleBizServiceImpl.getROleDetail(roleId);
    			roleList.add(role);
    		}
        }
		return roleList;
	}

	private  Long getNextId() {
		return customIdGeneratorBizServiceImpl.getId();
	}
	
	private void addRoles(Long bizttypeId, List<Long> roleIds) {
		if (roleIds == null || roleIds.size() == 0) {
			return;
		}
		// 批量添加新角色
		List<HashMap<String, Object>> biztypeRoles = new ArrayList<HashMap<String, Object>>();
		String tenantIdStr = (String) InvocationInfoProxy.getTenantid();
		Long tenantId = Long.parseLong(tenantIdStr);
		for (int i = 0; i < roleIds.size(); i++) {
			Long roleId = Long.valueOf(String.valueOf(roleIds.get(i)));
			HashMap<String, Object> biztypeRole = new HashMap<String, Object>();
			biztypeRole.put("tenantId", tenantId);
			biztypeRole.put("biztypeId", bizttypeId);
			biztypeRole.put("roleId", roleId);
			biztypeRoles.add(biztypeRole);
		}

		dao.saveSql(BiztypeRoleVO.class,"BatchInsertBiztypeRole",biztypeRoles);
	}
	
	public List<BiztypeVO> getBiztypeListByRoleId(Long objId, Long roleId) {
		String tenantIdStr = (String) InvocationInfoProxy.getTenantid();
		Long tenantId = Long.parseLong(tenantIdStr);
		Map<String, Object> paramMap = new HashMap<String, Object>();

		paramMap.put("tenantId", tenantId);
		paramMap.put("roleId", roleId);
		List<BiztypeVO> allBiztpes = getBiztypeList(objId);	
		List<Long> biztypes = new ArrayList<Long>();
		for (BiztypeVO biztypeVO:allBiztpes) {
			biztypes.add(biztypeVO.getId());
		}
		paramMap.put("biztypeIds", biztypes);
		
		List<BiztypeRoleVO> biztypeRoleVOs = dao.selectVoList(BiztypeRoleVO.class, "ListBiztypeByRole",paramMap);
		Map<Long, BiztypeVO> biztypesMap = new HashMap<Long, BiztypeVO>();
		for (BiztypeVO biztypeVO : allBiztpes) {
			biztypesMap.put(biztypeVO.getId(), biztypeVO);
		}
		Boolean isCustom = false;
		for (BiztypeRoleVO biztypeRoleVO : biztypeRoleVOs) {
			if (biztypeRoleVO.getTenantId() != 0) {
				isCustom = true;
				break;
			}
		}
		BiztypeVO defaultBiztypeVO = getDefaultBiztype(allBiztpes);
		List<BiztypeVO> rsBiztypeVOs = new ArrayList<BiztypeVO>();
		if (defaultBiztypeVO != null) {
			rsBiztypeVOs.add(defaultBiztypeVO);
		}
		Iterator<BiztypeRoleVO> it = biztypeRoleVOs.iterator();
		while (it.hasNext()) {
			BiztypeRoleVO biztypeRoleVO = it.next();
			if (biztypeRoleVO.getTenantId() == 0 && isCustom) {
				continue;
			} else if (biztypesMap.containsKey(biztypeRoleVO.getBiztypeId())) {
				BiztypeVO biztypeVO = biztypesMap.get(biztypeRoleVO.getBiztypeId());
				if (biztypeVO.getIsEnabled() == 1 && biztypeVO.getIsDeleted() ==0) {
					rsBiztypeVOs.add(biztypeVO);
				}
			}
		}
		return rsBiztypeVOs;
	}
	
	public List<BiztypeVO> getAvailabelBiztypesForCurrentRole(Long objId) {
		String roleIdStr = InvocationInfoProxy.getParameter(LoginContextConstant.RoleId);
		Long roleId = Long.parseLong(roleIdStr);
		return getBiztypeListByRoleId(objId,roleId);	
	}
	
	public BiztypeVO getDefaultBiztype(Long objId) {
		List<BiztypeVO> biztypeVOs = getBiztypeList(objId);
		BiztypeVO defaultBiztypeVO = null;
		for (BiztypeVO biztypeVO: biztypeVOs) {
			if (biztypeVO.getIsDefault() == 1) {
				defaultBiztypeVO = biztypeVO;
				if (biztypeVO.getTenantId() == 1) {
					break;
				}
			}
		}
		return defaultBiztypeVO;	
	}
	
	public BiztypeVO getDefaultBiztype(List<BiztypeVO> biztypeVOs) {
		BiztypeVO defaultBiztypeVO = null;
		for (BiztypeVO biztypeVO: biztypeVOs) {
			if (biztypeVO.getIsDefault() == 1) {
				defaultBiztypeVO = biztypeVO;
				if (biztypeVO.getTenantId() != 0) {
					break;
				}
			}
		}
		return defaultBiztypeVO;	
	}
	
	/**
	 * 通过ID数组获取id和name的map列表
	 * @param ids
	 * @return
	 */
	public Object selectFieldsByIds(Object[] ids) {
		String tenantIdStr = (String) InvocationInfoProxy.getTenantid();
		Long tenantId = Long.parseLong(tenantIdStr);
		Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("tenantId", tenantId);
		paramMap.put("ids", ids);
		List<Map<String, Object>> biztypeList = new ArrayList<Map<String,Object>>();
		biztypeList =dao.selectList(BiztypeVO.class, "selectFieldsByIds", paramMap);
		List<Object> customBiztypes = new ArrayList<Object>();
		BigInteger zero = new BigInteger("0");
		for (Map<String, Object> biztype : biztypeList) {
			if (!((BigInteger)biztype.get("tenant_id")).equals(zero)) {
				customBiztypes.add(biztype.get("id"));
			}
		}
		Iterator<Map<String, Object>> it = biztypeList.iterator();
		while (it.hasNext()) {
			Map<String, Object> biztype = it.next();
			if (((BigInteger)biztype.get("tenant_id")).equals(zero)
					&& customBiztypes.contains(biztype.get("id"))) {
				it.remove();
			} else {
				biztype.remove("tenant_id");
			}
		}
		return biztypeList;
	}
	
	/**
	 * 给PC端用
	 * @param objId
	 * @return
	 */
	public Map<String, Object> getModuleBiztypesForCurrentRole(Long objId) {
		String roleIdStr = InvocationInfoProxy.getParameter(LoginContextConstant.RoleId);
		Long roleId = Long.parseLong(roleIdStr);
		List<BiztypeVO> biztypeVOs = getBiztypeListByRoleId(objId,roleId);	
		Map<String, Object> rs = new HashMap<String, Object>();
		List<Map<String, Object>> biztypes = new ArrayList<Map<String,Object>>();
		rs.put("objId", objId);
		for (BiztypeVO biztypeVO : biztypeVOs) {
			Map<String, Object> biztypeMap = new HashMap<String, Object>();
			biztypeMap.put("key", biztypeVO.getId());
			biztypeMap.put("title", biztypeVO.getName());
			biztypes.add(biztypeMap);
		}
		rs.put("biztypeList", biztypes);	
		return rs;
	}

	/**
	 * 给PC端用
	 * @param objId
	 * @return
	 */
	public Map<String, Object> getModuleBiztypesForCurrentRole(String objName) {
		String roleIdStr = InvocationInfoProxy.getParameter(LoginContextConstant.RoleId);
		Long roleId = Long.parseLong(roleIdStr);
		ModuleVO moduleVO = moduleBizServiceImpl.getModule(objName);
		Long objId = moduleVO.getId();
		List<BiztypeVO> biztypeVOs = getBiztypeListByRoleId(objId,roleId);
		Map<String, Object> rs = new HashMap<String, Object>();
		List<Map<String, Object>> biztypes = new ArrayList<Map<String,Object>>();
		rs.put("objId", objId);
		for (BiztypeVO biztypeVO : biztypeVOs) {
			Map<String, Object> biztypeMap = new HashMap<String, Object>();
			biztypeMap.put("key", biztypeVO.getId());
			biztypeMap.put("title", biztypeVO.getName());
			biztypes.add(biztypeMap);
		}
		rs.put("biztypeList", biztypes);	
		return rs;
	}

	public void deleteBiztype(Long biztypeId) {
		String tenantIdStr = (String) InvocationInfoProxy.getTenantid();
		Long tenantId = Long.parseLong(tenantIdStr);
		String userIdStr = (String)InvocationInfoProxy.getParameter("id");//用户id
		Long userId = Long.parseLong(userIdStr);

		BiztypeVO biztypeVO = new BiztypeVO();
		biztypeVO.setTenantId(tenantId);
		biztypeVO.setId(biztypeId);
		BiztypeVO originalBiztype = getBiztype(biztypeVO.getId());
		
		// 预置业务类型不允许删除
		deletionCheck(originalBiztype);
		
		Date date = new Date();
		biztypeVO.setIsDeleted(1);
		biztypeVO.setDeletedTime(date);
		biztypeVO.setDeletedUserId(userId);
		biztypeVO.setSysModifiedTime(date);
		biztypeVO.setSysModifiedUserId(userId);
		super.updateVO(biztypeVO);
		BiztypeDeleteEvent event = new BiztypeDeleteEvent(biztypeVO);
		publisher.publishEvent(event);
	}
	
	public void saveBiztypeEnableStatus(Long biztypeId) {
		BiztypeVO biztypeVO = new BiztypeVO();
		BiztypeVO originalBiztypeVO = getBiztype(biztypeId);
		biztypeVO.setId(biztypeId);
		biztypeVO.setIsEnabled(1);
		disableCheck(originalBiztypeVO);
		updateBiztypeOnly(biztypeVO);
	}
	
	public void saveBiztypeDisableStatus(Long biztypeId) {
		BiztypeVO originalBiztype = getBiztype(biztypeId);
		// 预置业务类型不允许停用
		disableCheck(originalBiztype);
		BiztypeVO biztypeVO = new BiztypeVO();
		biztypeVO.setId(biztypeId);
		biztypeVO.setIsEnabled(0);
		updateBiztypeOnly(biztypeVO);
	}
	
	private void deletionCheck(BiztypeVO biztypeVO) {
		String userIdStr = (String)InvocationInfoProxy.getParameter("id");//用户id
		Long userId = Long.parseLong(userIdStr);
		if (!administratorManage.isAdmin(userId)) {
			throw new CrmBusinessException("没有该功能的操作权限");
		}
		if (biztypeVO.getIsCustom() == 0) {
			throw new CrmBusinessException("不能删除预置业务类型");
		}
	}
	
	private void disableCheck(BiztypeVO biztypeVO) {
		String userIdStr = (String)InvocationInfoProxy.getParameter("id");//用户id
		Long userId = Long.parseLong(userIdStr);
		if (!administratorManage.isAdmin(userId)) {
			throw new CrmBusinessException("没有该功能的操作权限");
		}
		if (biztypeVO.getIsDefault() == 1) {
			throw new CrmBusinessException("不能停用默认业务类型");
		}
	}
	
	 @EventListener
	 public void onBiztypeDelete(BiztypeDeleteEvent event) {
		 Map<String, Object> paramMap = new HashMap<String, Object>();
		 String tenantIdStr = (String) InvocationInfoProxy.getTenantid();
		 Long tenantId = Long.parseLong(tenantIdStr);
		 paramMap.put("tenantId", tenantId);
		 paramMap.put("biztypeId", event.getBiztype().getId());
		 dao.delete(BiztypeRoleVO.class, "DeleteByBiztypeId", paramMap);
	 }
	 
	 private void updateBiztypeOnly(BiztypeVO biztypeVO) {
		String tenantIdStr = (String) InvocationInfoProxy.getTenantid();
		Long tenantId = Long.parseLong(tenantIdStr);
		String userIdStr = (String) InvocationInfoProxy.getParameter("id");// 用户id
		Long userId = Long.parseLong(userIdStr);

		biztypeVO.setTenantId(tenantId);
		BiztypeVO originalBiztype = getBiztype(biztypeVO.getId());
		// 不是为了更新，而是为了返回用
		biztypeVO.setIsDefault(originalBiztype.getIsDefault());
		biztypeVO.setIsCustom(originalBiztype.getIsCustom());
		Date date = new Date();
		biztypeVO.setModifiedTime(date);
		biztypeVO.setSysModifiedTime(date);
		biztypeVO.setSysModifiedUserId(userId);
		biztypeVO.setModifiedUserId(userId);

		if (originalBiztype.getTenantId() == 0) {
			biztypeVO.setSysCreatedTime(date);
			biztypeVO.setCreatedTime(originalBiztype.getCreatedTime());
			biztypeVO.setObjId(originalBiztype.getObjId());
			biztypeVO.setSortOrder(originalBiztype.getSortOrder());
			super.saveVO(biztypeVO);
		} else {
			super.updateVO(biztypeVO);
		}
	 }
	 
	 public void batchUpdateEnableState(String[] idArray, Integer enableState) {
		Byte en = (byte) enableState.intValue();
		Map<String, Object> enableParaMap = new HashMap<String, Object>();
		enableParaMap.put("ids", idArray);
		enableParaMap.put("enableState", en);
		dao.updateSql(BiztypeVO.class, "batchUpdateEnableState", enableParaMap);
		}
}
